Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | /**
* Addon Check Middleware
* Verifies if a system addon is installed and active before allowing access
*
* @module middleware/addonCheck
*/
const { pool } = require('../config/database');
const { logger } = require('../config/logger');
/**
* Cache for addon status to avoid repeated database queries
* Cache expires after 60 seconds
*/
const addonCache = new Map();
const CACHE_TTL = 60000; // 60 seconds
/**
* Check if a system addon is installed and active
* @param {string} addonSlug - The slug of the addon to check
* @returns {Promise<{installed: boolean, active: boolean}>}
*/
async function checkAddonStatus(addonSlug) {
const cacheKey = `addon_${addonSlug}`;
const cached = addonCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.status;
}
try {
const [addons] = await pool.execute(
'SELECT id, active FROM system_addons WHERE slug = ?',
[addonSlug]
);
const status = {
installed: addons.length > 0,
active: addons.length > 0 && (addons[0].active === 1 || addons[0].active === true)
};
addonCache.set(cacheKey, { status, timestamp: Date.now() });
return status;
} catch (error) {
logger.error('Error checking addon status', { addonSlug, error: error.message });
// If table doesn't exist, addon system is not set up
return { installed: false, active: false };
}
}
/**
* Clear addon cache (useful when addon status changes)
* @param {string} [addonSlug] - Optional specific addon to clear, or all if not provided
*/
function clearAddonCache(addonSlug) {
if (addonSlug) {
addonCache.delete(`addon_${addonSlug}`);
} else {
addonCache.clear();
}
}
/**
* Middleware factory to require a specific addon to be active
* @param {string} addonSlug - The slug of the required addon
* @returns {Function} Express middleware
*/
function requireAddon(addonSlug) {
return async (req, res, next) => {
try {
const status = await checkAddonStatus(addonSlug);
if (!status.installed) {
return res.status(403).json({
success: false,
message: `The ${addonSlug} addon is not installed. Please contact your administrator.`,
error: 'ADDON_NOT_INSTALLED',
addon: addonSlug
});
}
if (!status.active) {
return res.status(403).json({
success: false,
message: `The ${addonSlug} addon is not active. Please contact your administrator.`,
error: 'ADDON_NOT_ACTIVE',
addon: addonSlug
});
}
// Addon is installed and active, proceed
next();
} catch (error) {
logger.error('Error in requireAddon middleware', { addonSlug, error: error.message });
return res.status(500).json({
success: false,
message: 'Error checking addon status'
});
}
};
}
/**
* Get all active addons
* @returns {Promise<Array>} List of active addons
*/
async function getActiveAddons() {
try {
const [addons] = await pool.execute(
'SELECT slug, name, icon, config FROM system_addons WHERE active = 1'
);
return addons;
} catch (error) {
logger.error('Error getting active addons', { error: error.message });
return [];
}
}
module.exports = {
checkAddonStatus,
clearAddonCache,
requireAddon,
getActiveAddons
};
|